home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 16
/
Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso
/
Aminet
/
comm
/
term
/
term_source.lha
/
Extras
/
Source
/
term-source.lha
/
Boxes.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-20
|
13KB
|
742 lines
/*
** Boxes.c
**
** Text box management support routines
**
** Copyright © 1990-1996 by Olaf `Olsen' Barthel
** All Rights Reserved
**
** :ts=4
*/
#ifndef _GLOBAL_H
#include "Global.h"
#endif
/* Sizing data. */
STATIC struct RastPort *SZ_RPort;
STATIC struct TextFont *SZ_TextFont;
STATIC struct Screen *SZ_Screen;
STATIC LONG SZ_Left,
SZ_Top,
SZ_CurrentLeft,
SZ_CurrentTop,
SZ_CurrentWidth,
SZ_MaxWidth,
SZ_TextPen,
SZ_BackPen,
SZ_AverageGlyphWidth;
/* SZ_SetTopEdge(LONG Top):
*
* Set the current object top edge.
*/
VOID
SZ_SetTopEdge(LONG Top)
{
SZ_CurrentTop = Top;
}
/* SZ_SetLeftEdge(LONG Left):
*
* Set the current object left edge.
*/
VOID
SZ_SetLeftEdge(LONG Left)
{
SZ_CurrentLeft = Left;
}
/* SZ_SetAbsoluteTop(LONG Top):
*
* Set new inner window top edge.
*/
VOID
SZ_SetAbsoluteTop(LONG Top)
{
SZ_Top = Top;
}
/* SZ_SetWidth(LONG Width):
*
* Set current object width.
*/
VOID
SZ_SetWidth(LONG Width)
{
SZ_CurrentWidth = Width;
}
/* SZ_AddLeftOffset(LONG Offset):
*
* Update current object left offset.
*/
VOID
SZ_AddLeftOffset(LONG Offset)
{
SZ_CurrentLeft += Offset;
}
/* SZ_LeftOffsetN(LONG DataArray,...):
*
* Determine the maximum length of a number of
* gadget labels (first, second, third item, -1 terminates
* the array).
*/
LONG
SZ_LeftOffsetN(LONG DataArray,...)
{
LONG *Data = &DataArray,
Len,
Max = 0;
STRPTR String;
while(*Data != -1)
{
String = LocaleString(*Data++);
if((Len = TextLength(SZ_RPort,String,strlen(String))) > Max)
Max = Len;
}
return(Max + INTERWIDTH);
}
/* SZ_SizeCleanup():
*
* Free data allocated by SZ_SizeSetup().
*/
VOID
SZ_SizeCleanup()
{
if(SZ_TextFont)
{
CloseFont(SZ_TextFont);
SZ_TextFont = NULL;
}
FreeVecPooled(SZ_RPort);
SZ_RPort = NULL;
}
/* SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr):
*
* Perform setups for gadget creation.
*/
BOOL
SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr)
{
SZ_SizeCleanup();
if(Screen)
{
struct DrawInfo *DrawInfo;
if(DrawInfo = GetScreenDrawInfo(Screen))
{
SZ_TextPen = DrawInfo->dri_Pens[TEXTPEN];
SZ_BackPen = DrawInfo->dri_Pens[BACKGROUNDPEN];
FreeScreenDrawInfo(Screen,DrawInfo);
}
}
else
{
if(!TextAttr)
return(FALSE);
}
SZ_Screen = Screen;
if(SZ_RPort = (struct RastPort *)AllocVecPooled(sizeof(struct RastPort),MEMF_ANY | MEMF_CLEAR))
{
InitRastPort(SZ_RPort);
if(!TextAttr)
TextAttr = Screen->Font;
if(SZ_TextFont = SmartOpenDiskFont(TextAttr))
{
LONG i,Width,Counted = 0,NumericWidth = 0;
UBYTE Char;
InterWidth = INTERWIDTH;
if(SZ_TextFont->tf_YSize <= 8)
InterHeight = 1;
else
InterHeight = SZ_TextFont->tf_YSize / 4;
SetFont(SZ_RPort,SZ_TextFont);
SZ_AverageGlyphWidth = 0;
for(i = 32 ; i < 127 ; i++)
{
Char = i;
Width = TextLength(SZ_RPort,&Char,1);
/* For really pathologic fonts... */
if(Width < 0 || Width > 32767)
continue;
SZ_AverageGlyphWidth += Width;
Counted++;
}
for(i = 160 ; i < 256 ; i++)
{
Char = i;
Width = TextLength(SZ_RPort,&Char,1);
/* For really pathologic fonts... */
if(Width < 0 || Width > 32767)
continue;
SZ_AverageGlyphWidth += Width;
Counted++;
}
for(i = '0' ; i < '9' ; i++)
{
Char = i;
Width = TextLength(SZ_RPort,&Char,1);
if(Width > NumericWidth)
NumericWidth = Width;
}
Char = ' ';
Width = TextLength(SZ_RPort,&Char,1);
if(Width > NumericWidth)
NumericWidth = Width;
SZ_AverageGlyphWidth /= Counted;
if(SZ_AverageGlyphWidth < NumericWidth)
SZ_AverageGlyphWidth = NumericWidth;
SZ_Left = InterWidth;
if(Screen)
SZ_Top = Screen->WBorTop + Screen->Font->ta_YSize + 1 + InterHeight;
else
SZ_Top = 0;
SZ_CurrentLeft = InterWidth;
SZ_CurrentTop = SZ_Top;
SZ_CurrentWidth = 0;
SZ_MaxWidth = 0;
return(TRUE);
}
}
SZ_SizeCleanup();
return(FALSE);
}
/* SZ_GetLen(STRPTR String):
*
* Get the string pixel width, measured using the average
* glyph width.
*/
ULONG
SZ_GetLen(STRPTR String)
{
return(strlen(String) * SZ_AverageGlyphWidth);
}
/* SZ_FreeBox(struct TextBox *Box):
*
* Free a text box.
*/
STATIC VOID
SZ_FreeBox(struct TextBox *Box)
{
if(Box)
{
if(Box->Text)
{
LONG i;
for(i = 0 ; i < Box->NumLines ; i++)
{
if(Box->Text[i])
FreeVecPooled(Box->Text[i]);
}
FreeVecPooled(Box->Text);
}
FreeVecPooled(Box->Title);
FreeVecPooled(Box);
}
}
/* SZ_FreeBoxes(struct TextBox *FirstBox):
*
* Free a number of text boxes.
*/
VOID
SZ_FreeBoxes(struct TextBox *FirstBox)
{
if(FirstBox)
{
struct TextBox *NextBox;
do
{
NextBox = FirstBox->NextBox;
SZ_FreeBox(FirstBox);
FirstBox = NextBox;
}
while(FirstBox);
}
}
/* SZ_BoxWidth(LONG Chars):
*
* Determine the width of a text box.
*/
LONG
SZ_BoxWidth(LONG Chars)
{
return((LONG)(4 + SZ_AverageGlyphWidth * Chars + 4));
}
/* SZ_BoxHeight(LONG Lines):
*
* Determine the height of a text box.
*/
LONG
SZ_BoxHeight(LONG Lines)
{
return(2 + SZ_TextFont->tf_YSize * Lines + 2);
}
/* SZ_CreateTextBox(struct TextBox **FirstBox,...):
*
* Create a text box, this routine works similar
* to the CreateGadget() frontend.
*/
struct TextBox *
SZ_CreateTextBox(struct TextBox **FirstBox,...)
{
va_list VarArgs;
struct TagItem *TagList,
*ThisTag;
LONG Chars,Lines,
Width,
Height,
Left = SZ_CurrentLeft;
BOOL AutoWidth = FALSE,
MoveDown = TRUE,
SetLeft = FALSE,
SetBelow = FALSE;
struct TextBox *Box;
LONG i;
va_start(VarArgs,FirstBox);
TagList = (struct TagItem *)VarArgs;
if(ThisTag = FindTagItem(SZ_Lines,TagList))
Lines = (LONG)ThisTag->ti_Data;
else
return(NULL);
Height = 2 + SZ_TextFont->tf_YSize * Lines + 2;
if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
AutoWidth = ThisTag->ti_Data;
if(!AutoWidth)
return(NULL);
else
Chars = (SZ_CurrentWidth - 8) / SZ_AverageGlyphWidth;
if(!(Box = (struct TextBox *)AllocVecPooled(sizeof(struct TextBox),MEMF_ANY | MEMF_CLEAR)))
return(NULL);
if(ThisTag = FindTagItem(SZ_NewColumn,TagList))
{
if(ThisTag->ti_Data)
{
SZ_CurrentTop = SZ_Top;
Left = Left + SZ_MaxWidth + InterWidth;
SZ_MaxWidth = 0;
}
}
if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
AutoWidth = ThisTag->ti_Data;
if(!AutoWidth)
Width = SZ_BoxWidth(Chars);
else
Width = SZ_CurrentWidth;
Box->Left = Left;
Box->Top = SZ_CurrentTop;
Box->Width = Width;
Box->Height = Height;
Box->LineWidth = Chars * SZ_AverageGlyphWidth;
Box->LineHeight = SZ_TextFont->tf_YSize;
Box->NumChars = Chars;
Box->NumLines = Lines;
Box->TitleFgPen = SZ_TextPen;
Box->TitleBgPen = SZ_BackPen;
Box->TextPen = SZ_TextPen;
if(!(Box->Title = (STRPTR *)AllocVecPooled(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
{
SZ_FreeBox(Box);
return(NULL);
}
if(!(Box->Text = (STRPTR *)AllocVecPooled(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
{
SZ_FreeBox(Box);
return(NULL);
}
for(i = 0 ; i < Lines ; i++)
{
if(!(Box->Text[i] = (STRPTR)AllocVecPooled(Chars + 1,MEMF_ANY | MEMF_CLEAR)))
{
SZ_FreeBox(Box);
return(NULL);
}
}
if(SetBelow)
MoveDown = FALSE;
if(MoveDown)
SZ_CurrentTop = SZ_CurrentTop + Height + InterHeight;
else
SZ_MaxWidth = 0;
if(Width > SZ_MaxWidth)
SZ_MaxWidth = Width;
if(!SetLeft)
SZ_CurrentLeft = Left;
if(!(*FirstBox))
*FirstBox = Box;
else
{
struct TextBox *CurrentBox = *FirstBox;
while(CurrentBox->NextBox)
CurrentBox = CurrentBox->NextBox;
CurrentBox->NextBox = Box;
}
return(Box);
}
/* SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...):
*
* Set the titles displayed in a text box.
*/
VOID
SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...)
{
if(Box)
{
STRPTR *Data = &Array;
LONG i = 0;
while(*Data != NULL)
{
if(i < Box->NumLines)
Box->Title[i++] = *Data;
Data++;
}
}
}
/* SZ_SetLine():
*
* Print a string into a text box, plain version.
*/
VOID
SZ_SetLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String)
{
LONG FgPen = ReadAPen(RPort),
BgPen = ReadBPen(RPort),
DrMd = ReadDrMd(RPort);
struct TextFont *Font = RPort->Font;
LONG Width,Len,
Left = Box->Left + 4,
Top = Box->Top + 2 + Line * Box->LineHeight;
SetPens(RPort,Box->TextPen,SZ_BackPen,JAM2);
if(Font != UserTextFont)
SetFont(RPort,UserTextFont);
if(Len = strlen(String))
{
if(Len > Box->NumChars)
Len = Box->NumChars;
Len = FitText(RPort,Box->LineWidth,String,Len);
if(Len)
{
Width = TextLength(RPort,String,Len);
PlaceText(RPort,Left,Top,String,Len);
}
else
Width = 0;
}
else
Width = 0;
if(Width != Box->LineWidth)
{
if(FgPen != SZ_BackPen)
{
SetAPen(RPort,SZ_BackPen);
RectFill(RPort,Left + Width,Top,Left + Box->LineWidth - 1,Top + Box->LineHeight - 1);
SetAPen(RPort,FgPen);
}
else
RectFill(RPort,Left + Width,Top,Left + Box->LineWidth - 1,Top + Box->LineHeight - 1);
}
SetPens(RPort,FgPen,BgPen,DrMd);
if(String != Box->Text[Line])
{
if(Len > 0)
CopyMem(String,Box->Text[Line],Len);
Box->Text[Line][Len] = 0;
}
if(Font != UserTextFont)
SetFont(RPort,Font);
}
/* SZ_PrintLine():
*
* Print a string into a text box, varargs version.
*/
VOID
SZ_PrintLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String,...)
{
va_list VarArgs;
UBYTE Buffer[256];
va_start(VarArgs,String);
LimitedVSPrintf(sizeof(Buffer),Buffer,String,VarArgs);
va_end(VarArgs);
SZ_SetLine(RPort,Box,Line,Buffer);
}
/* SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box):
*
* (Re-)Draw a text box.
*/
STATIC VOID
SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box)
{
if(Box)
{
LONG LineY,i,Len,FgPen = ReadAPen(RPort),BgPen = ReadBPen(RPort),DrMd = ReadDrMd(RPort);
struct TextFont *Font = RPort->Font;
if(Font != UserTextFont)
SetFont(RPort,UserTextFont);
if(FgPen != SZ_BackPen)
{
SetAPen(RPort,SZ_BackPen);
FillBox(RPort,Box->Left,Box->Top,Box->Width,Box->Height);
SetAPen(RPort,FgPen);
}
else
FillBox(RPort,Box->Left,Box->Top,Box->Width,Box->Height);
DrawBevelBox(RPort,Box->Left,Box->Top,Box->Width,Box->Height,
GT_VisualInfo, VisualInfo,
GTBB_Recessed, TRUE,
TAG_DONE);
LineY = Box->Top + 2;
SetPens(RPort,Box->TitleFgPen,Box->TitleBgPen,JAM2);
for(i = 0 ; i < Box->NumLines ; i++)
{
if(Len = strlen(Box->Title[i]))
PlaceText(RPort,Box->Left - INTERWIDTH - TextLength(RPort,Box->Title[i],Len),LineY,Box->Title[i],Len);
LineY += Box->LineHeight;
}
for(i = 0 ; i < Box->NumLines ; i++)
SZ_PrintLine(RPort,Box,i,Box->Text[i]);
SetPens(RPort,FgPen,BgPen,DrMd);
if(Font != UserTextFont)
SetFont(RPort,Font);
}
}
/* SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox):
*
* (Re-)Draw a number of text boxes.
*/
VOID
SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox)
{
do
SZ_DrawBox(RPort,FirstBox);
while(FirstBox = FirstBox->NextBox);
}
/* SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top):
*
* Change the location of a text box.
*/
STATIC VOID
SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top)
{
Box->Left += Left;
Box->Top += Top;
}
/* SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top):
*
* Change the locations of a number of text boxes.
*/
VOID
SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top)
{
do
SZ_MoveBox(FirstBox,Left,Top);
while(FirstBox = FirstBox->NextBox);
}
/* SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top):
*
* Set the location of a text box.
*/
STATIC VOID
SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top)
{
if(Left >= 0)
Box->Left = Left;
if(Top >= 0)
Box->Top = Top;
}
/* SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top):
*
* Set the locations of a number of text boxes.
*/
VOID
SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top)
{
do
SZ_SetBox(FirstBox,Left,Top);
while(FirstBox = FirstBox->NextBox);
}
/* SZ_GetBoxInfo(struct TextBox *Box,LONG Type):
*
* Query information on a certain text box.
*/
LONG
SZ_GetBoxInfo(struct TextBox *Box,LONG Type)
{
switch(Type)
{
case BOX_LEFT:
return(Box->Left);
case BOX_TOP:
return(Box->Top);
case BOX_WIDTH:
return(Box->Width);
case BOX_HEIGHT:
return(Box->Height);
default:
return(0);
}
}